#ifndef __TXN_STAT_H__
#define __TXN_STAT_H__

#include <atomic.h>
#include <noncopyable.h>
#include <cgi_control.h>
#include <Lock.h>
#include <map>

HTTP_SVR_NS_BEGIN

class CStatManager;

#if HAS_ATOMIC8
struct CStatItem
{
public:
	typedef int64_t V;

	~CStatItem(void) { }
	CStatItem(void) { ptr = (atomic8_t *)&dummy; }
	CStatItem(volatile V *p) : ptr((atomic8_t *)p) { }
	CStatItem(const CStatItem &f) : ptr(f.ptr) { }

	inline V get(void) const { return atomic8_read(ptr); }
	inline V set(V v) { atomic8_set(ptr, v); return v; }
	inline V add(V v) { return atomic8_add_return(v, ptr); }
	inline V sub(V v) { return atomic8_sub_return(v, ptr); }
	inline V clear(void) { return atomic8_clear(ptr);  }
	inline V inc(void) { return add(1); }
	inline V dec(void) { return sub(1); }
	inline operator V(void) const { return get(); }
	inline V operator= (V v) { return set(v); }
	inline V operator+= (V v) { return add(v); }
	inline V operator-= (V v) { return sub(v); }
	inline V operator++ (void) { return inc(); }
	inline V operator-- (void) { return dec(); }
	inline V operator++ (int) { return inc()-1; }
	inline V operator-- (int) { return dec()+1; }

private:
	static int64_t dummy;
	atomic8_t *ptr;

};
typedef CStatItem CStatItemU32;
typedef CStatItem CStatItemS32;

#else
struct CStatItemU32
{
public:
	typedef uint32_t V;

	~CStatItemU32(void) { }
	CStatItemU32(void) { ptr = (atomic_t *)&dummy; }
	CStatItemU32(volatile V *p) : ptr((atomic_t *)p) { }
	CStatItemU32(const CStatItemU32 &f) : ptr(f.ptr) { }

	inline V get(void) const { return atomic_read(ptr); }
	inline V set(V v) { atomic_set(ptr, v); return v; }
	inline V add(V v) { return atomic_add_return(v, ptr); }
	inline V sub(V v) { return atomic_sub_return(v, ptr); }
	inline V clear(void) { return atomic_clear(ptr);  }
	inline V inc(void) { return add(1); }
	inline V dec(void) { return sub(1); }
	inline operator V(void) const { return get(); }
	inline V operator= (V v) { return set(v); }
	inline V operator+= (V v) { return add(v); }
	inline V operator-= (V v) { return sub(v); }
	inline V operator++ (void) { return inc(); }
	inline V operator-- (void) { return dec(); }
	inline V operator++ (int) { return inc()-1; }

private:
	static uint32_t dummy;
	atomic_t *ptr;
inline V operator-- (int) { return dec()+1; }
};

struct CStatItemS32
{
public:
	typedef int32_t V;

	~CStatItemS32(void) { }
	CStatItemS32(void) { ptr = (atomic_t *)&dummy; }
	CStatItemS32(volatile V *p) : ptr((atomic_t *)p) { }
	CStatItemS32(const CStatItemS32 &f) : ptr(f.ptr) { }

	inline V get(void) const { return atomic_read(ptr); }
	inline V set(V v) { atomic_set(ptr, v); return v; }
	inline V add(V v) { return atomic_add_return(v, ptr); }
	inline V sub(V v) { return atomic_sub_return(v, ptr); }
	inline V clear(void) { return atomic_clear(ptr);  }
	inline V inc(void) { return add(1); }
	inline V dec(void) { return sub(1); }
	inline operator V(void) const { return get(); }
	inline V operator= (V v) { return set(v); }
	inline V operator+= (V v) { return add(v); }
	inline V operator-= (V v) { return sub(v); }
	inline V operator++ (void) { return inc(); }
	inline V operator-- (void) { return dec(); }
	inline V operator++ (int) { return inc()-1; }

private:
	static int32_t dummy;
	atomic_t *ptr;
inline V operator-- (int) { return dec()+1; }
};
#endif

typedef CStatItemU32::V TItemU32;
typedef CStatItemS32::V TItemS32;

typedef struct
{
    TItemU32        _web_req_count;
    TItemU32        _web_rsp_count;

    TItemU32        _helper_req_count;
    TItemU32        _helper_rsp_count;

    char            _cgi_data[0];
} TStatHeadInfo __attribute__((__aligned__(4)));

typedef struct
{
    int             _cgi_index;
    TItemU32        _cgi_req_count;
    TItemU32        _cgi_rsp_count;
} TCGIStatData __attribute__((__aligned__(4)));

class CStatManager : private noncopyable
{
    typedef struct
    {
        CStatItemU32*   _cgi_req;
        CStatItemU32*   _cgi_rsp;
        TCGIStatData*   _cgi_stat_data;
    } TCGIOperInfo;

public:
    CStatManager (void);
    ~CStatManager (void);

    static CStatManager* Instance (void);
    static void Destroy (void);

public:

    int open(void);
    int release(void);
    //web request
    inline TItemU32 web_req_inc (void)
    {
        return _web_req_u32->inc ();
    }
    inline TItemU32 web_req_dec (void)
    {
        return _web_req_u32->dec ();
    }
    inline TItemU32 web_req_add (TItemU32 value)
    {
        return _web_req_u32->add (value);
    }
    inline TItemU32 web_req_sub (TItemU32 value)
    {
        return _web_req_u32->sub (value);
    }
    //web response
    inline TItemU32 web_rsp_inc (void)
    {
        return _web_rsp_u32->inc ();
    }
    inline TItemU32 web_rsp_dec (void)
    {
        return _web_rsp_u32->dec ();
    }
    inline TItemU32 web_rsp_add (TItemU32 value)
    {
        return _web_rsp_u32->add (value);
    }
    inline TItemU32 web_rsp_sub (TItemU32 value)
    {
        return _web_rsp_u32->sub (value);
    }
    
    //helper request 
    inline TItemU32 helper_req_inc (void)
    {
        return _helper_req_u32->inc ();
    }
    inline TItemU32 helper_req_dec (void)
    {
        return _helper_req_u32->dec ();
    }
    inline TItemU32 helper_req_add (TItemU32 value)
    {
        return _helper_req_u32->add (value);
    }
    inline TItemU32 helper_req_sub (TItemU32 value)
    {
        return _helper_req_u32->sub (value);
    }
    //helper response
    inline TItemU32 helper_rsp_inc (void)
    {
        return _helper_rsp_u32->inc ();
    }
    inline TItemU32 helper_rsp_dec (void)
    {
        return _helper_rsp_u32->dec ();
    }
    inline TItemU32 helper_rsp_add (TItemU32 value)
    {
        return _helper_rsp_u32->add (value);
    }
    inline TItemU32 helper_rsp_sub (TItemU32 value)
    {
        return _helper_rsp_u32->sub (value);
    }
 
    TItemU32 add_req_by_id (int item_id, TItemU32 value);
    TItemU32 sub_req_by_id (int item_id, TItemU32 value);
    TItemU32 add_rsp_by_id (int item_id, TItemU32 value);
    TItemU32 sub_rsp_by_id (int item_id, TItemU32 value);

    inline TItemU32 inc_req_by_id (int item_id)
    {
        return add_req_by_id (item_id, 1);
    }
    inline TItemU32 inc_rsp_by_id (int item_id)
    {
        return add_rsp_by_id (item_id, 1);
    }
    inline TItemU32 dec_req_by_id (int item_id)
    {
        return sub_req_by_id (item_id, 1);
    }
    inline TItemU32 dec_rsp_by_id (int item_id)
    {
        return sub_rsp_by_id (item_id, 1);
    }
    
public:

protected:
protected:

private:
    void* get_stat_mem (const char* filename, int size);
    int init_cgi_stat_item (void);
    int clear (void);

    static void* __threadentry(void *);
    int run (void);

private:
    typedef std::map <int, TCGIOperInfo*> TStatItemMap;

    uint16_t        _cycle;

    TStatHeadInfo*  _stathead;
    CStatItemU32*   _web_req_u32;
    CStatItemU32*   _web_rsp_u32;
    CStatItemU32*   _helper_req_u32;
    CStatItemU32*   _helper_rsp_u32;

    TStatItemMap    _itemmap;
    pthread_t       threadid;
    pthread_mutex_t wakeLock;
    CMutex          _mutex;
};

HTTP_SVR_NS_END

#endif //__TXN_STAT_H__
